package com.app.tool;


import java.util.ArrayList;
import java.util.List;


public class BytesUtil {
    public BytesUtil() {
    }

    public static String getStrings(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02x", bytes[i]));
        }
        return sb.toString();
    }

    public static String getStrings(byte sbyte) {
        byte[] bytes = new byte[1];
        for (int i = 0; i < 1; i++) {
            bytes[i] = ((byte) (sbyte & 0xFF));
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02x", bytes[i]));
        }
        return sb.toString();
    }

    public static byte[] fill(byte[] srcBytes, byte value) {
        byte[] bytes = new byte[srcBytes.length];
        for (int i = 0; i < srcBytes.length; i++) {
            bytes[i] = value;
        }
        return bytes;
    }

    public static byte[] fill(byte[] srcBytes, char value) {
        byte[] bytes = new byte[srcBytes.length];
        for (int i = 0; i < srcBytes.length; i++) {
            bytes[i] = (byte) (value & 0xff);
        }
        return bytes;
    }

    public static byte[] fill(byte[] srcBytes, int value) {
        byte[] bytes = new byte[srcBytes.length];
        for (int i = 0; i < srcBytes.length; i++) {
            bytes[i] = (byte) (value & 0xff);
        }
        return bytes;
    }

    public static byte[] clr2blankByte(byte[] srcBytes) {
        byte[] bytes;
        int i;
        for (i = 0; i < srcBytes.length; i++) {
            if (srcBytes[i] == 0x00) {
                srcBytes[i] = 0x20;
            }
        }
        bytes = new byte[i];
        System.arraycopy(srcBytes, 0, bytes, 0, i);
        return bytes;
    }

    public static byte[] clrblankByte(byte[] srcBytes) {
        byte[] bytes;
        int i;
        for (i = 0; i < srcBytes.length; i++) {
            if (srcBytes[i] == 0x20) {
                break;
            }
        }
        bytes = new byte[i];
        System.arraycopy(srcBytes, 0, bytes, 0, i);
        return bytes;
    }

    public static byte[] clearblankByte(char[] srcBytes) {
        byte[] bytes;
        byte[] btmp = new byte[srcBytes.length];
        int i;
        for (i = 0; i < srcBytes.length; i++) {
            if (srcBytes[i] == 0x00) {
                break;
            }
            btmp[i] = (byte) srcBytes[i];
        }
        bytes = new byte[i];
        System.arraycopy(btmp, 0, bytes, 0, i);
        return bytes;
    }

    public static byte[] clearblankByte(byte[] srcBytes) {
        byte[] bytes;
        int i;
        for (i = 0; i < srcBytes.length; i++) {
            if (srcBytes[i] == 0x00) {
                break;
            }
        }
        bytes = new byte[i];
        System.arraycopy(srcBytes, 0, bytes, 0, i);
        return bytes;
    }

    public static byte[] subByte(byte[] srcBytes, int offset, int len) {
        byte[] bytes;
        if (srcBytes == null) {
            return null;
        }

        if ((len > srcBytes.length) || (offset + len > srcBytes.length) ||
                (offset >= srcBytes.length)) {
            return null;
        }

        if (len == -1) {
            bytes = new byte[srcBytes.length - offset];
            System.arraycopy(srcBytes, offset, bytes, 0, srcBytes.length - offset);
        } else {
            bytes = new byte[len];
            System.arraycopy(srcBytes, offset, bytes, 0, len);
        }
        return bytes;
    }

    public static byte[] mergeBytes(byte[] bytesA, byte[] bytesB) {
        if ((bytesA == null) || (bytesA.length == 0))
            return bytesB;
        if ((bytesB == null) || (bytesB.length == 0)) {
            return bytesA;
        }

        byte[] bytes = new byte[bytesA.length + bytesB.length];

        System.arraycopy(bytesA, 0, bytes, 0, bytesA.length);
        System.arraycopy(bytesB, 0, bytes, bytesA.length, bytesB.length);

        return bytes;
    }

    public static byte[] merge(byte[]... data) {
        if (data == null) {
            return null;
        }
        byte[] bytes = null;
        for (int i = 0; i < data.length; i++) {
            bytes = mergeBytes(bytes, data[i]);
        }
        return bytes;
    }

    public static int bytecmp(byte[] hex1, byte[] hex2, int len) {
        for (int i = 0; i < len; i++) {
            if (hex1[i] != hex2[i]) {
                return 1;
            }
        }

        return 0;
    }

    public static int bytecmp(char[] hex1, char[] hex2, int len) {
        for (int i = 0; i < len; i++) {
            if (hex1[i] != hex2[i]) {
                return 1;
            }
        }

        return 0;
    }

    public static byte[] hexString2ByteArray(String hexStr) {
        if (hexStr == null)
            return null;
        if (hexStr.length() % 2 != 0) {
            hexStr = hexStr + "0";
        }
        byte[] data = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            char hc = hexStr.charAt(2 * i);
            char lc = hexStr.charAt(2 * i + 1);
            byte hb = hexChar2Byte(hc);
            byte lb = hexChar2Byte(lc);
            if ((hb < 0) || (lb < 0)) {
                return null;
            }
            int n = hb << 4;
            data[i] = ((byte) (n + lb));
        }
        return data;
    }

    public static byte hexChar2Byte(char c) {
        if ((c >= '0') && (c <= '9'))
            return (byte) (c - '0');
        if ((c >= 'a') && (c <= 'f'))
            return (byte) (c - 'a' + 10);
        if ((c >= 'A') && (c <= 'F'))
            return (byte) (c - 'A' + 10);
        return -1;
    }

    public static String byteArray2HexString(byte[] arr, int len) {
        int temp;
        StringBuilder sb = new StringBuilder();
        if (len < arr.length) {
            temp = len;
        } else {
            temp = arr.length;
        }
        for (int i = 0; i < temp; i++) {
            sb.append(String.format("%02x", new Object[]{Byte.valueOf(arr[i])}).toUpperCase());
        }
        return sb.toString();
    }

    public static String byteArray2HexString(byte[] arr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            sb.append(String.format("%02x", Byte.valueOf(arr[i])).toUpperCase());
        }
        return sb.toString();
    }

    public static String byteArray2HexString(List<Byte> arrList) {
        byte[] arr = new byte[arrList.size()];
        for (int i = 0; i < arrList.size(); i++) {
            arr[i] = ((Byte) arrList.get(i)).byteValue();
        }
        return byteArray2HexString(arr);
    }

    public static String byteArray2HexStringWithSpace(byte[] arr) {
        StringBuilder sbd = new StringBuilder();
        byte[] arrayOfByte = arr;
        int j = arr.length;
        for (int i = 0; i < j; i++) {
            byte b = arrayOfByte[i];
            String tmp = Integer.toHexString(0xFF & b);
            if (tmp.length() < 2)
                tmp = "0" + tmp;
            sbd.append(tmp);
            sbd.append(" ");
        }
        return sbd.toString();
    }

    public static String getBCDString(byte[] data, int start, int end) {
        byte[] t = new byte[end - start + 1];
        System.arraycopy(data, start, t, 0, t.length);
        return byteArray2HexString(t);
    }

    public static String getHexString(byte[] data, int start, int end) {
        byte[] t = new byte[end - start + 1];
        System.arraycopy(data, start, t, 0, t.length);
        return byteArray2HexStringWithSpace(t);
    }

    public static byte[] toByteArray(int source, int len) {
        byte[] bLocalArr = new byte[len];
        for (int i = 0; (i < 4) && (i < len); i++) {
            bLocalArr[(len - 1 - i)] = ((byte) (source >> 8 * i & 0xFF));
        }
        return bLocalArr;
    }

    public static byte[] BCD_To_Hex(byte[] bcd, int bcd_len) {
        byte[] ascii = new byte[bcd_len];
        int j = 0;
        for (int i = 0; i < bcd_len; i++) {
            ascii[i] = (byte) (((bcd[j]) / 10) << 4);
            ascii[i] += bcd[j] % 10;
            j++;
        }
        return ascii;
    }

    public static byte[] Hex_To_BCD(byte[] ascii, int asc_len) {
        byte[] bcd = new byte[asc_len];
        int j = 0;
        for (int i = 0; i < asc_len; i++) {
            bcd[i] = (byte) (((ascii[j] & 0xf0) >> 4) * 10);
            bcd[i] += ascii[j] & 0x0f;
            j++;
        }
        return bcd;
    }

    public static byte[] Hex2String(byte[] hex, int hex_len) {
        byte[] bcd = new byte[hex_len * 2];

        for (int i = 0; i < hex_len; i++) {
            bcd[2 * i] = (byte) (((hex[i] & 0xf0) >> 4) + '0');
            bcd[2 * i + 1] = (byte) ((hex[i] & 0x0f) + '0');
        }
        return bcd;
    }


    public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
        byte[] bcd = new byte[(asc_len + 1) / 2];
        int j = 0;
        for (int i = 0; i < (asc_len + 1) / 2; i++) {
            bcd[i] = asc_to_bcd(ascii[(j++)]);
            bcd[i] = ((byte) ((j >= asc_len ? 0 : asc_to_bcd(ascii[(j++)])) + (bcd[i] << 4)));
        }
        return bcd;
    }

    private static byte asc_to_bcd(byte asc) {
        byte bcd;
        if ((asc >= 48) && (asc <= 57)) {
            bcd = (byte) (asc - 48);
        } else {
            if ((asc >= 65) && (asc <= 70)) {
                bcd = (byte) (asc - 65 + 10);
            } else {
                if ((asc >= 97) && (asc <= 102)) {
                    bcd = (byte) (asc - 97 + 10);
                } else {
                    bcd = (byte) (asc - 48);
                }
            }
        }
        return bcd;
    }

    public static boolean[] getBooleanArray(byte b) {
        boolean[] array = new boolean[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = ((b & 0x1) == 1 ? true : false);
            b = (byte) (b >> 1);
        }
        return array;
    }

    public static int booleanArray2i(boolean[] b) {
        int res = 0;
        int len = b.length;
        for (int i = 0; i < len; i++) {
            if (b[i] != false) {
                res += (int) Math.pow(2.0D, len - i - 1);
            }
        }
        return res;
    }

    public static int byte2Int(byte[] b) {
        int temp = 0;
        for (int i = 0; i < b.length; i++) {
            temp += ((b[i] & 0xFF) << 8 * (b.length - i - 1));
        }
        return temp;
    }

    public static int byte2Int(byte[] b, int bytesNum) {
        int intValue = 0;
        for (int i = 0; i < b.length; i++) {
            intValue += ((b[i] & 0xFF) << 8 * (bytesNum - 1 - i));
        }
        return intValue;
    }

    public static byte[] int2Bytes(int length, int bytesNum) {
        if (bytesNum > 4) {
            bytesNum = 4;
        } else if (bytesNum <= 0) {
            bytesNum = 1;
        }

        if (bytesNum == 4)
            return new byte[]{(byte) (length >> 24 & 0xFF), (byte) (length >> 16 & 0xFF), (byte) (length >> 8 & 0xFF), (byte) (length & 0xFF)};
        if (bytesNum == 3)
            return new byte[]{(byte) (length >> 16 & 0xFF), (byte) (length >> 8 & 0xFF), (byte) (length & 0xFF)};
        if (bytesNum == 2) {
            return new byte[]{(byte) (length >> 8 & 0xFF), (byte) (length & 0xFF)};
        }
        return new byte[]{(byte) (length & 0xFF)};
    }

    public static String asc2Bcd(String str) {
        byte[] bcd = ASCII_To_BCD(str.getBytes(), str.length());
        return bcd2Str(bcd);
    }

    private static String bcd2Str(byte[] bytes) {
        char[] temp = new char[bytes.length * 2];

        for (int i = 0; i < bytes.length; i++) {
            char val = (char) ((bytes[i] & 0xF0) >> 4 & 0xF);
            temp[(i * 2)] = ((char) (val > '\t' ? val + 'A' - 10 : val + '0'));

            val = (char) (bytes[i] & 0xF);
            temp[(i * 2 + 1)] = ((char) (val > '\t' ? val + 'A' - 10 : val + '0'));
        }
        return new String(temp);
    }

    public static byte[] hex2byte(String str) {
        int len = str.length();
        String stmp = null;
        byte[] bt = new byte[len / 2];
        for (int n = 0; n < len / 2; n++) {
            stmp = str.substring(n * 2, n * 2 + 2);
            bt[n] = ((byte) Integer.parseInt(stmp, 16));
        }
        return bt;
    }

    public static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0xFF);
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }

    public static List<Byte> hexString2ByteList(String dataStr) {
        byte[] dataArray = hexString2ByteArray(dataStr);
        List<Byte> result = new ArrayList<Byte>();
        for (int i = 0; i < dataArray.length; i++) {
            result.add(Byte.valueOf(dataArray[i]));
        }
        return result;
    }

    public static boolean isBitSet(byte val, int bitPos) {
        if ((bitPos < 1) || (bitPos > 8)) {
            throw new IllegalArgumentException("parameter 'bitPos' must be between 1 and 8. bitPos=" + bitPos);
        }
        if ((val >> bitPos - 1 & 0x1) == 1) {
            return true;
        }
        return false;
    }

    public static boolean isAsciiByte(byte[] srcBytes) {
        for (int i = 0; i < srcBytes.length; i++) {
            if ((srcBytes[i] >= '0' && srcBytes[i] <= '9')
                    || (srcBytes[i] >= 'A' && srcBytes[i] <= 'Z')
                    || (srcBytes[i] >= 'a' && srcBytes[i] <= 'z')) {

            } else {
                return false;
            }
        }
        return true;
    }

    public static byte[] makeDistanceBytes(int distance) {
        int fiveKm = 0;
        int fourKm = 0;
        int threeKm = 0;
        int twoKm = 0;
        int oneKm = 0;
        int halfOfOneKm = 0;

        fiveKm = distance / 5000;
        distance -= 5000 * fiveKm;

        fourKm = distance / 4000;
        distance -= 4000 * fourKm;

        threeKm = distance / 3000;
        distance -= 3000 * threeKm;

        twoKm = distance / 2000;
        distance -= 2000 * twoKm;

        oneKm = distance / 1000;
        distance -= 1000 * oneKm;

        if (distance != 0) {
            halfOfOneKm = 1;
        }

        byte[] distanceBytes = new byte[fiveKm + fourKm + threeKm + twoKm + oneKm + halfOfOneKm];
        int k = 0;
        if (fiveKm > 0) {
            for (int i = 0; i < fiveKm; i++) {
                distanceBytes[(k++)] = 5;
            }
        }

        if (fourKm > 0) {
            for (int i = 0; i < fourKm; i++) {
                distanceBytes[(k++)] = 4;
            }
        }

        if (threeKm > 0) {
            for (int i = 0; i < threeKm; i++) {
                distanceBytes[(k++)] = 3;
            }
        }

        if (twoKm > 0) {
            for (int i = 0; i < twoKm; i++) {
                distanceBytes[(k++)] = 2;
            }
        }

        if (oneKm > 0) {
            for (int i = 0; i < oneKm; i++) {
                distanceBytes[(k++)] = 1;
            }
        }

        if (halfOfOneKm > 0) {
            for (int i = 0; i < halfOfOneKm; i++) {
                distanceBytes[(k++)] = 0;
            }
        }

        return distanceBytes;
    }

    public static int getDistanceFromBytes(byte[] addBytes) {
        if ((addBytes == null) || (addBytes.length == 0)) {
            return 0;
        }

        int km = 0;
        for (int i = 0; i < addBytes.length; i++) {
            if ((addBytes[i] & 0xFF) == 0) {
                km += 500;
            } else if ((addBytes[i] & 0xFF) == 1) {
                km += 1000;
            } else if ((addBytes[i] & 0xFF) == 2) {
                km += 2000;
            } else if ((addBytes[i] & 0xFF) == 3) {
                km += 3000;
            } else if ((addBytes[i] & 0xFF) == 4) {
                km += 4000;
            } else if ((addBytes[i] & 0xFF) == 5) {
                km += 5000;
            }
        }

        return km;
    }
}

